﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Common.DataTypes;
using System.Xml;
using System.IO;
using Common;
using System.Xml.Serialization;
using System.Linq;

namespace LinqAmazonProvider
{
    public static class ResultXMLParser
    {
        public static CollectionOfAmazonBook ParseXmlQueryResult(string xmlResult)
        {
            CollectionOfAmazonBook ABookCollection = null;

            try
            {
                XmlReader xmlReader = XmlReader.Create(new StringReader(xmlResult));

                XmlSerializer xSerializer = new XmlSerializer(typeof(CollectionOfAmazonBook));

                ABookCollection = (CollectionOfAmazonBook)xSerializer.Deserialize(xmlReader);
            }
            catch (Exception e)
            {
            }

            return (ABookCollection);
        }

        public static int GetTotalPagesQueryResult(string xmlResult)
        {
            CollectionOfAmazonBook ABookCollection = ResultXMLParser.ParseXmlQueryResult(xmlResult);

            return (ABookCollection.ResultData.TotalPages);
        }

        public static object GetQueryResult(List<string> serializedObj, Dictionary<string, string> parameters)
        {
            Object result = null;
            CollectionOfAmazonBook ABookCollection = new CollectionOfAmazonBook();
            List<Book> listResult = new List<Book>();
            string method = parameters["Method"];

            try
            {
                foreach (string xmlResult in serializedObj)
                {
                    ABookCollection = ResultXMLParser.ParseXmlQueryResult(xmlResult);
                    ABookCollection.Language = parameters["Language"];

                    listResult.AddRange(ABookCollection.RetrieveBooks());
                }

                switch (method)
                {
                    case "Count":
                        result = ABookCollection.GetTotalResults();
                        break;
                    case "First":
                        if (listResult.Count > 0)
                        {
                            if (parameters.ContainsKey("Skip"))
                            {
                                int numberOfItemsToSkip = int.Parse(parameters["Skip"]);
                                if (numberOfItemsToSkip < listResult.Count)
                                {
                                    result = listResult[numberOfItemsToSkip];
                                }
                                else {
                                    result = null;
                                }
                            }
                            else {
                                // Don't have any number of items to skip, so return the first element
                                result = listResult[0];
                            }
                        }
                        else
                        {
                            result = null;
                        }

                        break;
                    case "Last":
                        if (listResult.Count > 0)
                        {
                            List<Book> resultTemp = (List<Book>) ResultXMLParser.GetResultCollection(listResult, parameters);

                            if (resultTemp.Count > 0)
                            {
                                result = resultTemp[resultTemp.Count - 1];
                            }
                            else {
                                result = null;
                            }
                        }
                        else
                        {
                            result = null;
                        }

                        break;
                    default:
                        result = ResultXMLParser.GetResultCollection(listResult, parameters);

                        if (parameters.ContainsKey("Select"))
                        {
                            result = ResultXMLParser.GetResultBySelect(parameters["Select"], result);
                        }
                        break;
                }
            }
            catch (Exception e)
            {
            }
            return (result);
        }

        private static object GetResultCollection(List<Book> currentResult, Dictionary<string, string> parameters) {
            object result;
            if (parameters.ContainsKey("Skip"))
            {
                int numberOfItemsToSkip = int.Parse(parameters["Skip"]);
                if (numberOfItemsToSkip >= currentResult.Count)
                {
                    // if number of items to skip is grater than number of items of result collection, return emtpy collection
                    result = new List<Book>();
                }
                else
                {
                    if (parameters.ContainsKey("Take"))
                    {
                        int numberItemsToTake = Convert.ToInt32(Math.Min(currentResult.Count - numberOfItemsToSkip, int.Parse(parameters["Take"])));
                        result = currentResult.GetRange(numberOfItemsToSkip, numberItemsToTake);
                    }
                    else
                    {
                        result = currentResult.GetRange(numberOfItemsToSkip, currentResult.Count - numberOfItemsToSkip);
                    }
                }
            }
            else if (parameters.ContainsKey("Take"))
            {
                int numberOfItemsToReturn = Convert.ToInt32(Math.Min(currentResult.Count, int.Parse(parameters["Take"])));

                result = currentResult.GetRange(0, numberOfItemsToReturn);
            }
            else
            {
                result = currentResult;
            }

            return (result);
        }

        private static object GetResultBySelect(string selectType, object result)
        {
            object newResult = null;
            List<Book> books = (List<Book>)result;

            #region Query Result
            switch (selectType)
            {
                case "Title":
                    var query = from book in books
                                select book.Title;
                    newResult = query.ToList<String>();
                    break;
                case "Isbn":
                    query = from book in books
                            select book.Isbn;
                    newResult = query.ToList<String>();
                    break;
                case "PublicationDate":
                    query = from book in books
                            select book.PublicationDate;
                    newResult = query.ToList<String>();
                    break;
                case "Publisher":
                    query = from book in books
                            select book.Publisher;
                    newResult = query.ToList<String>();
                    break;
                case "ReleaseDate":
                    query = from book in books
                            select book.ReleaseDate;
                    newResult = query.ToList<String>();
                    break;
                case "Asin":
                    query = from book in books
                            select book.AmazonNumber;
                    newResult = query.ToList<String>();
                    break;
                case "DetailPageUrl":
                    query = from book in books
                            select book.DetailPageUrl;
                    newResult = query.ToList<String>();
                    break;
                case "SalesRank":
                    query = from book in books
                            select book.SalesRank;
                    newResult = query.ToList<String>();
                    break;
                case "SmallImage":
                    query = from book in books
                            select book.SmallImage;
                    newResult = query.ToList<String>();
                    break;
                case "MediumImage":
                    query = from book in books
                            select book.MediumImage;
                    newResult = query.ToList<String>();
                    break;
                case "LargeImage":
                    query = from book in books
                            select book.LargeImage;
                    newResult = query.ToList<String>();
                    break;
                case "Manufacturer":
                    query = from book in books
                            select book.Manufacturer;
                    newResult = query.ToList<String>();
                    break;
                case "PackageDimensions":
                    query = from book in books
                            select book.PackageDimensions;
                    newResult = query.ToList<String>();
                    break;
                case "Label":
                    query = from book in books
                            select book.Label;
                    newResult = query.ToList<String>();
                    break;
                case "Studio":
                    query = from book in books
                            select book.Studio;
                    newResult = query.ToList<String>();
                    break;
                case "Binding":
                    query = from book in books
                            select book.Binding;
                    newResult = query.ToList<String>();
                    break;
                case "Ean":
                    query = from book in books
                            select book.EuropeanArticleNumber;
                    newResult = query.ToList<String>();
                    break;
                case "Condition":
                    query = from book in books
                            select book.Condition;
                    newResult = query.ToList<String>();
                    break;
                case "Category":
                    var queryInt = from book in books
                            select book.Category;
                    newResult = queryInt.ToList<int>();
                    break;
            }
            #endregion

            return (newResult);
        }
    }
}
